package org.ala.tiktools.rpc.spring;

import java.lang.annotation.Annotation;

import org.ala.tiktools.logs.LoggerFactory;
import org.ala.tiktools.rpc.client_server.client.AlaRpcClient;
import org.ala.tiktools.rpc.client_server.service.RpcServiceExecutor;
import org.ala.tiktools.rpc.config.RpcConfigInfo;
import org.ala.tiktools.rpc.config.RpcConfigInfoParse;
import org.ala.tiktools.rpc.exception.RpcRuntimeException;
import org.ala.tiktools.rpc.plugin.interceptor.RpcInterceptorChain;
import org.ala.tiktools.rpc.plugin.load_balance.ILoadBalance;
import org.ala.tiktools.rpc.plugin.load_balance.selector.ISelector;
import org.ala.tiktools.rpc.plugin.node.INodeCreator;
import org.ala.tiktools.rpc.plugin.serializer.SerializeThreadPool;
import org.ala.tiktools.tools.BeanTools;
import org.ala.tiktools.tools.ReflectionTools;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import io.netty.util.NettyRuntime;

/**
 *
 *  @author ala
 *  @date 2025-04-04 14:17
 */
public class RpcBeanRegisterPostProcessor implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware {


    static Logger log = LoggerFactory.getLogger("rpc", "init");


    /**
     *
     */
    protected Environment env;
    /**
     *
     */
    protected ResourceLoader resourceLoader;
    /**
     *
     */
    protected BeanDefinitionRegistry beanDefinitionRegistry;

    
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    	this.beanDefinitionRegistry = registry;
        //  解析配置
        try {
            RpcConfigInfoParse parser = new RpcConfigInfoParse();
            RpcConfigInfo.INSTANCE = parser.parse(env);

        } catch (ClassNotFoundException e) {
            throw new RpcRuntimeException(e);
        }

        //  注册默认的loadBalance NodeCreator NodeSelector
        registerSerializeThreadPool();
        registerLoadBalance(RpcConfigInfo.INSTANCE.getLoadBalanceClass());
        registerNodeCreator(RpcConfigInfo.INSTANCE.getNodeCreatorClass());
        registerNodeSelector(RpcConfigInfo.INSTANCE.getNodeSelectorClass());
        registerInterceptorChain();
        
        //  执行前置方法
        beforeParse();

        //  扫描客户端注解
        scanClient(importingClassMetadata, AlaRpcClient.class);

        //	启动服务端
        startServer();
    }
    /**
     *  解析前置操作
     */
    protected void beforeParse() {}
    
    
    
    
    /************************************************************************************************************************
     * 公共组件相关
     ************************************************************************************************************************/
    /**
     * 	注册序列化/反序列化线程池
     */
    protected void registerSerializeThreadPool() {
    	SerializeThreadPool.INSTANCE_SERIALIZER = ReflectionTools.newInstance(RpcConfigInfo.INSTANCE.getSerializeClass());
    	//	默认cpu核数 * 2
    	int core = RpcConfigInfo.INSTANCE.getSerializePoolSize();
    	if (core <= 0) { core = NettyRuntime.availableProcessors() * 2; }
    	SerializeThreadPool pool = SerializeThreadPool.build(core);
    	SerializeThreadPool.INSTANCE = pool;
    	BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_SERIALIZER_THREAD_POOL, pool, (b, d) -> d.setLazyInit(false));
    }


    
    
    /************************************************************************************************************************
     * 客户端相关
     ************************************************************************************************************************/
    /**
     *  注册默认的LoadBalance
     */
    protected void registerLoadBalance(Class<? extends ILoadBalance> clazz) {
        BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_LOAD_BALANCE, clazz, null);
    }
    /**
     *  注册默认的NodeCreator
     */
    @SuppressWarnings("rawtypes")
	protected void registerNodeCreator(Class<? extends INodeCreator> clazz) {
        BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_NODE_CREATOR, clazz, null);
    }
    /**
     *  注册默认的NodeSelector
     */
    protected void registerNodeSelector(Class<? extends ISelector> clazz) {
        BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_NODE_SELECTOR, clazz, null);
    }
    /**
     * 	初始化默认的拦截器链
     * 	@throws LinkageError 
     * 	@throws ClassNotFoundException 
     */
    protected void registerInterceptorChain() {
    	//	加载发送端公共拦截器
    	BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_INTERCEPTOR_SENDER_CHAIN, new RpcInterceptorChain(), (b, d) -> {
    		b.addPropertyValue("classes", RpcConfigInfo.INSTANCE.getInterceptorSenderChain());
    		d.setLazyInit(false);
    	});
    
    	//	加载接收端公共拦截器
    	BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_INTERCEPTOR_RECEIVER_CHAIN, new RpcInterceptorChain(), (b, d) -> {
    		b.addPropertyValue("classes", RpcConfigInfo.INSTANCE.getInterceptorReceiverChain());
    		d.setLazyInit(false);
    	});
    }


    /**
     * 扫描客户端注解，并生成BeanDefined
     */
    protected void scanClient(AnnotationMetadata metadata, Class<? extends Annotation> ac) {
        ClassPathScanningCandidateComponentProvider scanner = createScanner(env, resourceLoader, ac);
        
        //	优先取application.yml配置文件里的扫描目录
        String[] pkgs = RpcConfigInfo.INSTANCE.getRpcClientPackages();
        //	如果取不到取 Import 注解里的扫描目录
        if (pkgs == null || pkgs.length == 0) {
        	pkgs = pkgsFromAnnotation(metadata);
        }
        //	如果还取不到，取启动类的包目录
        if (pkgs == null || pkgs.length == 0) {
        	pkgs = new String[] {ClassUtils.getPackageName(metadata.getClassName())};
        }
        
        registerClientBeanDefine(pkgs, scanner);
    }
    /**
     * 	拿注解里要扫描的包
     */
    protected String[] pkgsFromAnnotation(AnnotationMetadata metadata) {return null;}
    /**
     * 	注册pkgs目录下的client bean
     */
    protected void registerClientBeanDefine(String[] pkgs, ClassPathScanningCandidateComponentProvider scanner) {
    	if (pkgs == null || pkgs.length == 0) { return; }
    	for (String pkg : pkgs) {
            if (StringUtils.isEmpty(pkg)) {continue;}
            scanner.findCandidateComponents(pkg).forEach(this::registerClientBeanDefine);
        }
    }
    /**
     *  注册客户端代理bean
     */
    protected void registerClientBeanDefine(BeanDefinition bd) {
        //  被代理的类型
        String beanClassName = bd.getBeanClassName();
        try {
            final Class<?> type = ClassUtils.forName(beanClassName, bd.getClass().getClassLoader());
            AlaRpcClient anno = type.getAnnotation(AlaRpcClient.class);
            if (!StringUtils.isEmpty(anno.contextId())) {
                beanClassName = anno.contextId();
            }
            //  构建并注册BeanDefine
            BeanTools.registerBeanDefined(beanDefinitionRegistry, beanClassName, RpcClientFactoryBean.class, (builder, beanDefined) -> {
                builder.addPropertyValue("type", type);
            });
        } catch (Exception e) {
            throw new RpcRuntimeException(e);
        }
    }
    
    
    
    
    /************************************************************************************************************************
     * 服务端相关
     ************************************************************************************************************************/
    /**
     * 	启动服务端
     */
    protected void startServer() {
    	registerRpcServiceExecutor();
    	registerRpcServiceReceiver();
    }
    /**
     * 	初始化执行器
     */
    protected void registerRpcServiceExecutor() {
    	BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_RPC_SERVICE_EXECUTOR, RpcServiceExecutor.class, (b,d) -> d.setLazyInit(false));
    }
    /**
     * 	初始化服务端接收器
     */
    protected void registerRpcServiceReceiver() {
    	BeanTools.registerBeanDefined(beanDefinitionRegistry, RpcBeanConfiguration.BEAN_RPC_SERVICE_RECEIVER, RpcConfigInfo.INSTANCE.getServiceReceiverClass(), (b,d) -> {
    		b.addPropertyReference("executor", RpcBeanConfiguration.BEAN_RPC_SERVICE_EXECUTOR);
    		d.setLazyInit(false);
    	});
    }



    
    /**
     * 初始化扫描器
     */
    protected ClassPathScanningCandidateComponentProvider createScanner(Environment env, ResourceLoader resourceLoader, Class<? extends Annotation> annoClass) {
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider() {
            @Override
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                if (beanDefinition.getMetadata().isIndependent()) {
                    if (
                            //  只接受接口类型的注解类
                            beanDefinition.getMetadata().isInterface()
//                                    && beanDefinition.getMetadata().getInterfaceNames().length == 1
//                                    && Annotation.class.getName().equals(beanDefinition.getMetadata().getInterfaceNames()[0])
                    ) {
                        try {
                            Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), this.getClass().getClassLoader());
                            //  不是注解类
                            return !target.isAnnotation();
                        } catch (ClassNotFoundException | LinkageError e) {
                            log.warn("[" + this.getClass().getSimpleName() + " createScanner] 加载类型错误:" + beanDefinition.getMetadata().getClassName(), e);
                        }
                    }
                    return true;
                }
                return false;
            }
        };

        scanner.setEnvironment(env);
        scanner.setResourceLoader(resourceLoader);

        //  要扫描的注解类型
        //	DelayMessageClient注解过滤器
        AnnotationTypeFilter annotationFilter = new AnnotationTypeFilter(annoClass);
        scanner.addIncludeFilter(annotationFilter);
        //	给scanner注册annotation过滤器和内部类过滤器
        //  不接受内部类
//        AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
//            @Override
//            protected boolean match(ClassMetadata metadata) {
//                //	内部类的$转换为.
//                String className = metadata.getClassName().replaceAll("\\$", ".");
//                return clientClasses.contains(className);
//            }
//        };
//        scanner.addIncludeFilter(new MultiTypeFilter(new TypeFilter[] {filter, annotationFilter}));
        return scanner;
    }



    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}
